home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
misc
/
btngo.zip
/
BTNGOC.ZIP
/
ITEMDATA.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-28
|
19KB
|
519 lines
#include<windows.h>
#include<ctype.h>
#include"wstring.hpp"
#include"itemdata.hpp"
#ifdef DEBUG_SCREENS
extern WinMessageString screen;
#endif
extern WinMessageString errscreen;
extern unsigned int winver;
/////////////////////////////////////
// defines
#define CFP(x) (&((char __far *)memptr)[x]) // create char __far * x bytes into buffer
#define CFP2(x) (&((char __far *)memptr2)[x]) // create char __far * x bytes into buffer
/////////////////////////////////////
// local data types
struct GroupInfo{
WORD name;
WORD executable;
WORD executable_with_path;
WORD parameters;
WORD default_directory;
WORD minimized;
};
struct GroupFileHeader{
char cIdentifier[4];
WORD wCheckSum;
WORD cbGroup;
WORD nCmdShow;
RECT rcNormal;
POINT ptMin;
WORD pName;
WORD wLogPixelsX;
WORD wLogPixelsY;
BYTE bBitsPerPixel;
BYTE bPlanes;
WORD wReserved;
WORD cItems;
};
struct ItemData{
POINT pt;
WORD iIcon; // 0 if normal, 1 if minimized
WORD cbResource;
WORD cbANDPlane;
WORD cbXORPlane;
WORD pHeader;
WORD pANDPlane;
WORD pXORPlane;
WORD pName;
WORD pCommand;
WORD pIconPath; // 0 or ptr to initial path
};
struct TagData{
WORD wID;
WORD wItem;
WORD cb;
union{
char cnext[1];
int inext;
}next;
};
struct IconHeader{ // pointed to by ItemData.pHeader
int xHotSpot;
int yHotSpot;
int cx; // icon width
int cy; // icon height
int cbWidth; // bytes per row including WORD alignment
BYTE bPlanes; // nbr planes
BYTE bBitsPixel; // bits per pixel
};
/////////////////////////////////////
// GroupFile member functions
GroupFile::GroupFile(char *p){
opened=0;
items_to_read=0;
tag_bytes=0;
memhandle=NULL;
memptr=NULL;
memhandle2=NULL;
memptr2=NULL;
got_icon_default_data=0;
set_filename(p);
}
GroupFile::~GroupFile(){
if(opened)_lclose(hf);
if(memhandle!=NULL){
if(memptr!=NULL)GlobalUnlock(memhandle);
GlobalFree(memhandle);
}
if(memhandle2!=NULL){
if(memptr2!=NULL)GlobalUnlock(memhandle2);
GlobalFree(memhandle2);
}
#ifdef DEBUG_SCREENS
screen<<grpfil<<" destructed\n";
screen.show();
#endif
}
void GroupFile::set_filename(char *p){
error_condition_exists=(NULL==(grpfil=p))?1:0;
}
int GroupFile::openfile(){
if(error())return 0;
// assume failure so can just return
error_condition_exists=1;
if(opened)return 0;
opened=((hf=_lopen(grpfil,READ))==HFILE_ERROR)?0:1;
if(!opened)return 0;
filebytes=_llseek(hf,0,2); // go to end of file
if(filebytes==HFILE_ERROR||_llseek(hf,0,0)==HFILE_ERROR)return 0; // go to beginning
if(filebytes>60000L){
errscreen<<"Group file is too large. Aborting.\n";
return 0;
}
if(filebytes<(sizeof(GroupFileHeader)+2+sizeof(ItemData)+sizeof(IconHeader))){
errscreen<<"Group file is empty or too small. Aborting.\n";
return 0;
}
if(NULL==(memhandle=GlobalAlloc(GMEM_FIXED,filebytes))){
errscreen<<"Could not allocate memory\n";
return 0;
}
if(NULL==(memptr=GlobalLock(memhandle))){
errscreen<<"Could not lock memory\n";
return 0;
}
if(_lread(hf,memptr,(UINT)filebytes)!=(UINT)filebytes){
errscreen<<"Could not read group file. Aborting.\n";
return 0;
}
GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
if(p->cIdentifier[0]!='P'||p->cIdentifier[1]!='M'||
p->cIdentifier[2]!='C'||p->cIdentifier[3]!='C'){
errscreen<<"Group file corrupted. Aborting.\n";
return 0;
}
pItemOffset=(int __far *)&p[1];
{
int ok=0;
for(;;){
WORD x;
if(p->cItems<1)break;
for(x=0;x<p->cItems;x++){
if(pItemOffset[x]!=0){
ok=1;
break;
}
}
break;
}
if(!ok){
errscreen<<"Group file is empty. Aborting.";
return 0;
}
}
_lclose(hf);
opened=0;
error_condition_exists=0;
return 1;
}
void GroupFile::readheader(){
if(error())return;
GroupFileHeader _far *p=(GroupFileHeader __far *)memptr;
// pItemOffset=(int *)&((GroupFileHeader *)memptr)[1];
items_to_read=p->cItems;
#ifdef DEBUG_SCREENS
screen<<"Group name is "<<CFP(p->pName)<<"\n";
#endif
// now, if in Win 3.1, associate tag data with items
// this is because the wItem part of TagData will become
// invalid (we'll need to sort the icons by position)
// so we'll use this convention:
// ItemData == TagData wID usage
// -------- ----------- -----------------------------
// iIcon 0x8103 0 if normal, 1 if minimized
// pIconPath 0x8101 0 or ptr to initial path
//
// pseudocode:
// set all iIcons to 0, pIconPaths to 0
// if in Windows 3.1 TagData may be present so
// for each TagData entry
// apply data to ItemData entry
// end for
// end if
{
int t;
ItemData __far *p;
for(t=0;t<items_to_read;t++){
if(pItemOffset[t]==0)continue;
p=(ItemData __far *)CFP(pItemOffset[t]);
p->iIcon=0;
p->pIconPath=0;
}
}
if(winver>=0x30A){
int keep_going=0;
GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
ItemData __far *q;
TagData __far *tdp;
if(filebytes>=(LONG)(p->cbGroup+6)){ // '6' sted sizeof(TagData) - sizeof(union)
tdp=(TagData __far *)CFP(p->cbGroup);
keep_going=1;
}
while(keep_going){
switch(tdp->wID){
case 0xFFFF: keep_going=0; break;
case 0x8101: // path in next.cnext
q=(ItemData __far *)CFP(pItemOffset[tdp->wItem]);
q->pIconPath=(WORD)(tdp->next.cnext-(char __far *)memptr);
break;
case 0x8103: // app should be minimized
q=(ItemData __far *)CFP(pItemOffset[tdp->wItem]);
q->iIcon=1;
break;
}
// '6' in next line is sizeof(TagData) - sizeof(union)
if((LONG)(((char __far *)tdp-(char __far *)memptr)+tdp->cb+6)>filebytes){
keep_going=0;
continue;
}
tdp=(TagData __far *)(((char __far *)tdp)+tdp->cb);
}
}
// ok now we can sort the item data by the icon's position
// so the group looks like it ought to
// use old'n'lame selection sort but it's good enough here...
if(items_to_read>1){
int min,x,left=items_to_read;
unsigned int temp;
unsigned int __far *p=(unsigned int __far *)pItemOffset;
while(left-->1){
for(x=0,min=0;x<=left;x++)if(second_lower(p[min],p[x]))min=x;
if(min!=0){temp=p[min];p[min]=*p;*p=temp;}
p++;
}
}
// now create the compacted version of the file
// first accumulate target size, then allocate space, then copy space
unsigned long size=0;
{
int left=items_to_read,found_items=0;
unsigned int __far *p=(unsigned int __far *)pItemOffset;
ItemData __far *i;
while(left&&*p){
i=(ItemData __far *)CFP(*p);
size+=sizeof(GroupInfo); // space for array entry
if(i->pName)size+=1+lstrlen(CFP(i->pName)); // space for entry's displayed name
if(i->pCommand)size+=1+lstrlen(CFP(i->pCommand)); // space for command line
if(i->pIconPath)size+=1+lstrlen(CFP(i->pIconPath)); // space for command path
p++;
left--;
found_items++;
}
items_to_read=found_items; // 'forget' about NULL entries
}
// now we know how much memory to get
// let's get it
if(size>0)for(;;){
if(NULL==(memhandle2=GlobalAlloc(GMEM_FIXED,size))){
errscreen<<"Could not allocate memory for program data\n";
break;
}
if(NULL==(memptr2=GlobalLock(memhandle2))){
errscreen<<"Could not lock memory for program data\n";
break;
}
// now wind through group file
// pseudocode: while(items to process)
// copy data into *gi
// build and copy strings, put offsets into *gi
// increment ItemData pointer
// increment GroupInfo pointer
GroupInfo __far *gi=(GroupInfo __far *)memptr2;
char __far *space=(char __far *)&gi[items_to_read]; // point to string space
int x=items_to_read;
unsigned int __far *p=(unsigned int __far *)pItemOffset;
ItemData __far *id;
char nb1[250],nb2[250];
while(x--){
id=(ItemData __far *)CFP(*p);
gi->minimized=id->iIcon; // GroupInfo.minimized
gi->name=(WORD)(space-(char __far *)memptr2); // GroupInfo.name
lstrcpy(space,CFP(id->pName));
while(*space++); // point past null terminator
if(id->pCommand!=0)lstrcpy(nb1,CFP(id->pCommand)); // defdir\\exename parms
else nb1[0]=0;
if(id->pIconPath!=0)lstrcpy(nb2,CFP(id->pIconPath)); // exepath
else nb2[0]=0;
gi->executable_with_path=(WORD)(space-(char __far *)memptr2); // GroupInfo.executable_with_path
lstrcpy(space,nb2);
while(*space)space++; // point at null terminator; we'll append .EXE name
// now find .EXE name
// first scan off whitespace
char *nb1_begin=nb1;
while(isspace(*nb1_begin))nb1_begin++;
// now go to end of first arg
char *parms=nb1_begin;
while(*parms){
if(isspace(*parms))break;
parms++;
}
// parms points at whitespace between first arg and parameters
// kill the whitespace
while(*parms){
if(isspace(*parms)){
*parms=0;
parms++;
}
else break;
}
// now parms points at the parameters, or a null terminator
// nb1_begin points at defdir\\exename (whitespace stripped both ends)
// point exename at executable's name
char *exename=nb1_begin;
int got_defdir=0;
while(*exename)exename++; // point at null terminator
while(exename>nb1_begin){
exename--;
if(*exename=='\\'||*exename==':'){
got_defdir=(int)(exename-nb1_begin);
if(exename>nb1_begin&&exename[-1]==':')got_defdir++;
exename++;
break; // nb1_begin points at defdir; exename points at executable name
}
}
gi->executable=(WORD)(space-(char __far *)memptr2); // GroupInfo.executable
lstrcpy(space,exename);
while(*space++); // point past null terminator
if(*parms==0)gi->parameters=0; // GroupInfo.parameters
else{
gi->parameters=(WORD)(space-(char __far *)memptr2);
lstrcpy(space,parms);
while(*space++); // point past null terminator
}
if(got_defdir==0)gi->default_directory=0; // GroupInfo.default_directory
else{
gi->default_directory=(WORD)(space-(char __far *)memptr2);
while(got_defdir--)*space++=*nb1_begin++;
*space++=0; // make null terminator, go past it
}
p++;
gi++;
}
break;
}
}
int GroupFile::second_lower(unsigned int first,unsigned int second){
// compare function for GroupFile::readheader()
// returns 1 if second should be *before* first
if(!second)return 0; // it's null, never make it first
if(!first)return 1; // it's null so second *should* be first
// now we have two non-NULL entries. Make pointers to item data
ItemData __far *pfirst=(ItemData __far *)CFP(first);
ItemData __far *psecond=(ItemData __far *)CFP(second);
// Which has smaller Y value?
if(pfirst->pt.y > psecond->pt.y)return 1;
if(pfirst->pt.y < psecond->pt.y)return 0;
// OK, depend on X value
return (pfirst->pt.x > psecond->pt.x)?1:0;
}
int GroupFile::showitem(int offset){
/*
pseudocode:
bail out if already failed
set error_condition_exists to indicate failure
if read itemdata fails return
if read
set error_condition_exists to indicate success
returns 0 for no item found, 1 for valid item found
*/
if(error())return 0;
if(memptr==NULL)return 0;
if(offset>=items_to_read)return 0;
if(pItemOffset[offset]==0)return 0; //NULL entry
ItemData __far *p=(ItemData __far *)CFP(pItemOffset[offset]);
error_condition_exists=1;
// set default to failure, so we can just return on error
#ifdef DEBUG_SCREENS
screen<<offset<<" "<<CFP(p->pName)<<" ("<<CFP(p->pCommand)<<")\n";
#endif
// well, we got here so all must be well
error_condition_exists=0;
return 1;
}
char __far *GroupFile::get_group_name(){
if(error())return NULL;
if(memptr==NULL)return NULL;
GroupFileHeader __far *p=(GroupFileHeader __far *)memptr;
if(p->pName==0)return NULL;
return CFP(p->pName);
}
char __far *GroupFile::get_item_name(int offset){
/*
returns char * to item name if it's valid (non-null, has printables)
*/
if(error())return NULL;
if(memptr2==NULL)return NULL;
if(offset>=items_to_read)return NULL;
if(!((GroupInfo __far *)memptr2)[offset].name)return NULL;
return CFP2(((GroupInfo __far *)memptr2)[offset].name);
}
char __far *GroupFile::get_item_command(int offset){
/*
returns char * to item's command if it's valid (non-null, has printables)
*/
if(error())return NULL;
if(memptr2==NULL)return NULL;
if(offset>=items_to_read)return NULL;
if(!((GroupInfo __far *)memptr2)[offset].executable_with_path)return NULL;
return CFP2(((GroupInfo __far *)memptr2)[offset].executable_with_path);
}
char __far *GroupFile::get_item_command_nopath(int offset){
/*
returns char * to item's command if it's valid (non-null, has printables)
*/
if(error())return NULL;
if(memptr2==NULL)return NULL;
if(offset>=items_to_read)return NULL;
if(!((GroupInfo __far *)memptr2)[offset].executable)return NULL;
return CFP2(((GroupInfo __far *)memptr2)[offset].executable);
}
char __far *GroupFile::get_item_parameters(int offset){
if(error())return NULL;
if(memptr2==NULL)return NULL;
if(offset>=items_to_read)return NULL;
if(!((GroupInfo __far *)memptr2)[offset].parameters)return NULL;
return CFP2(((GroupInfo __far *)memptr2)[offset].parameters);
}
char __far *GroupFile::get_item_default_dir(int offset){
/*
returns char * to item's path if it's valid (non-null, has printables)
*/
if(error())return NULL;
if(memptr2==NULL)return NULL;
if(offset>=items_to_read)return NULL;
if(!((GroupInfo __far *)memptr2)[offset].default_directory)return NULL;
return CFP2(((GroupInfo __far *)memptr2)[offset].default_directory);
}
int GroupFile::is_item_iconized(int offset){
/*
returns 1 if item is to be run minimized, 0 if not
*/
if(error())return 0;
if(offset>=items_to_read)return NULL;
if(memptr2!=NULL)return (int)((GroupInfo __far *)memptr2)[offset].minimized;
if(memptr==NULL)return 0;
if(pItemOffset[offset]==0)return 0; //NULL entry
ItemData __far *p=(ItemData __far *)CFP(pItemOffset[offset]);
return (p->iIcon==0)?0:1;
}
HBITMAP GroupFile::get_fill_item_and_bitmap(int offset,int&x,int&y){
// caller's responsibility to delete bitmap!
if(error())return NULL;
if(memptr==NULL)return NULL;
if(offset>=items_to_read)return NULL;
if(pItemOffset[offset]==0)return NULL; //NULL entry
ItemData __far *pID=(ItemData __far *)CFP(pItemOffset[offset]);
IconHeader __far *pIH=(IconHeader __far *)CFP(pID->pHeader);
x=pIH->cx;
y=pIH->cy;
return CreateBitmap(pIH->cx,pIH->cy,1,1,(const void FAR*)CFP(pID->pANDPlane));
}
HBITMAP GroupFile::get_fill_item_xor_bitmap(int offset,int&x,int&y){
// caller's responsibility to delete bitmap!
if(error())return NULL;
if(memptr==NULL)return NULL;
if(offset>=items_to_read)return NULL;
if(pItemOffset[offset]==0)return NULL; //NULL entry
ItemData __far *pID=(ItemData __far *)CFP(pItemOffset[offset]);
IconHeader __far *pIH=(IconHeader __far *)CFP(pID->pHeader);
x=pIH->cx;
y=pIH->cy;
return CreateBitmap(pIH->cx,pIH->cy,pIH->bPlanes,pIH->bBitsPixel,(const void FAR*)CFP(pID->pXORPlane));
}
int GroupFile::get_icon_dimensions(int& height,int& width){
if(!got_icon_default_data)get_icon_default_data();
if(!got_icon_default_data){
height=0x20;
width=0x20;
return 1;
}
height=y_pixels;
width=x_pixels;
return 1;
}
UINT GroupFile::get_icon_planes(){
if(!got_icon_default_data)get_icon_default_data();
if(!got_icon_default_data)return 4;
return icon_planes;
}
UINT GroupFile::get_icon_pixelbits(){
if(!got_icon_default_data)get_icon_default_data();
if(!got_icon_default_data)return 4;
return icon_pixelbits;
}
void GroupFile::done_with_bitmaps(){
if(memhandle!=NULL){
if(memptr!=NULL)GlobalUnlock(memhandle);
GlobalFree(memhandle);
}
memhandle=NULL;
memptr=NULL;
}
void GroupFile::get_icon_default_data(){
HDC ic=CreateIC("DISPLAY",NULL,NULL,NULL);
if(ic!=NULL){
x_pixels=GetSystemMetrics(SM_CXICON);
y_pixels=GetSystemMetrics(SM_CYICON);
icon_planes=GetDeviceCaps(ic,PLANES);
icon_pixelbits=GetDeviceCaps(ic,BITSPIXEL);
got_icon_default_data=1;
DeleteDC(ic);
}
}